package com.yzt.p_base.utils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.ContextWrapper;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;

import com.yzt.p_base.AppUtils;
import com.yzt.p_base.R;

import java.lang.reflect.Field;

/**
 * author : bob
 * date   : 2022/11/29
 * desc   :
 */
public class ToastUtil {

    private static final Handler handler = new Handler(Looper.getMainLooper());

    private static Toast toast = null;

    private static long oneTime = 0;

    private static long twoTime = 0;

    private static CharSequence info = "";

    public static void showMessage(String msg) {
        if (msg != null && !TextUtils.isEmpty(msg)) {
            showMessage(msg, Toast.LENGTH_SHORT, -1);
        }
    }

    public static void showMessage(String msg, boolean isShort) {
        if (msg != null) {
            showMessage(msg, isShort ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG, -1);
        }
    }

    public static void showMessage(String msg, boolean isShort, int gravity) {
        if (msg != null) {
            showMessage(msg, isShort ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG, gravity);
        }
    }

    /**
     * 根据设置的文本显示
     */
    public static void showMessage(int msg) {
        showMessage(msg, Toast.LENGTH_SHORT);
    }

    /**
     * 显示一个文本并且设置时长
     */
    public static void showMessage(CharSequence msg, int len, int gravity) {

        if (msg == null || msg.equals("")) {
            return;
        }

        twoTime = System.currentTimeMillis();
        //跟上次的显示内容一样，就判断显示时间
        if (info.equals(msg)) {
            if (twoTime - oneTime > 1500) {
                cancel();
                showToastFun(msg, len, gravity);
            }
        } else {
            info = msg;
            cancel();
            showToastFun(msg, len, gravity);
        }

        oneTime = twoTime;
    }

    private static void showToastFun(final CharSequence msg, final int len, final int gravity) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                initToast((String) msg, len, gravity);
            }
        });
    }

    /**
     * 资源文件方式显示文本
     */
    public static void showMessage(final int msg, final int len) {
        showMessage(msg, len, -1);
    }

    /**
     * 资源文件方式显示文本
     */
    public static void showMessage(final int msg, final int len, final int gravity) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                cancel();
                initToast(AppUtils.getApp().getString(msg), len, gravity);
            }
        });
    }

    /**
     * 取消吐司显示
     */
    public static void cancel() {
        if (toast != null) {
            toast.cancel();
            toast = null;
        }
    }

    @SuppressLint("ShowToast")
    public static void initToast(String msg, int len, int gravity) {
        LayoutInflater inflate = LayoutInflater.from(AppUtils.getApp());
        View toastRoot = inflate.inflate(R.layout.view_toast_layout, null);
        TextView tv = toastRoot.findViewById(R.id.tv_info);
        if (toast == null) {
            toast = Toast.makeText(AppUtils.getContext(), msg, len);
        }

        tv.setText(msg);
        toast.setDuration(len);
        toast.setView(toastRoot);
        //解决sdk25 BadTokenException问题
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N_MR1) {
            setContextCompat(toast.getView(), new SafeToastContext(AppUtils.getContext(), toast));
        }

        if (gravity != -1) {
            toast.setGravity(gravity, 0, DisplayUtils.dip2px(60));
        } else {
            toast.setGravity(Gravity.BOTTOM, 0, DisplayUtils.dip2px(60));
        }
        toast.show();
    }

    private static void setContextCompat(@NonNull View view, @NonNull Context context) {
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N_MR1) {
            try {
                Field field = View.class.getDeclaredField("mContext");
                field.setAccessible(true);
                field.set(view, context);
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
    }

    static class SafeToastContext extends ContextWrapper {

        private final @NonNull Toast toast;

        SafeToastContext(@NonNull Context base, @NonNull Toast toast) {
            super(base);
            this.toast = toast;
        }

        @Override
        public Context getApplicationContext() {
            return new ApplicationContextWrapper(getBaseContext().getApplicationContext());
        }

        private final class ApplicationContextWrapper extends ContextWrapper {

            private ApplicationContextWrapper(@NonNull Context base) {
                super(base);
            }


            @Override
            public Object getSystemService(@NonNull String name) {
                if (Context.WINDOW_SERVICE.equals(name)) {
                    return new WindowManagerWrapper((WindowManager) getBaseContext().getSystemService(name));
                }
                return super.getSystemService(name);
            }
        }

        private final class WindowManagerWrapper implements WindowManager {

            private static final String TAG = "WindowManagerWrapper";
            private final @NonNull WindowManager base;

            private WindowManagerWrapper(@NonNull WindowManager base) {
                this.base = base;
            }

            @Override
            public Display getDefaultDisplay() {
                return base.getDefaultDisplay();
            }

            @Override
            public void removeViewImmediate(View view) {
                base.removeViewImmediate(view);
            }

            @Override
            public void addView(View view, ViewGroup.LayoutParams params) {
                try {
                    base.addView(view, params);
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
                base.updateViewLayout(view, params);
            }

            @Override
            public void removeView(View view) {
                base.removeView(view);
            }
        }
    }
}
